﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Data.Linq.SqlClient;
using System.Linq;
using System.Text;
using Quizz.DataRepository.Models;

namespace Quizz.Service.Log
{
    public class LoginLogService : QuizzDomainService<QuizzDataContext>
    {
        public LoginLog GetById(long id)
        {
            return CompiledLoginLogSerVice.GetById(DataContext, id);
        }

        public void Insert(LoginLog log)
        {
            DataContext.LoginLogs.InsertOnSubmit(log);
            DataContext.SubmitChanges();
        }

        public void Update(LoginLog log)
        {
            var original = this.DataContext.LoginLogs.FirstOrDefault(l => l.Id == log.Id);

            original.SessionId = log.SessionId;
            original.UserId = log.UserId;
            original.LoginTime = log.LoginTime;
            original.LogoutTime = log.LogoutTime;
            original.IsOnline = log.IsOnline;

            this.DataContext.SubmitChanges();
        }

        public void Delete(LoginLog log)
        {
            Delete(log.Id);
        }

        public void Delete(long id)
        {
            var sql = string.Format(@"SELETE [LoginLog] WHERE [Id] = '{0}'", id);
            ExecuteCommand(sql);
        }

        public LoginLog GetLastLogin(long userId)
        {
            return CompiledLoginLogSerVice.GetLastLogin(DataContext, userId);
        }

        public LoginLog GetBySessionId(string sessionId)
        {
            return CompiledLoginLogSerVice.GetBySessionId(DataContext, sessionId);
        }

        public int GetNumberOfLogin(DateTime date)
        {
            return CompiledLoginLogSerVice.GetNumberOfLogin(DataContext, date);
        }

        public IEnumerable<LoginLog> GetLoginLogs(DateTime fromDate, DateTime toDate)
        {
            return
                    this.DataContext.LoginLogs.Where(
                    l =>
                    (SqlMethods.DateDiffDay(fromDate, l.LoginTime) >= 0 &&
                     SqlMethods.DateDiffDay(l.LoginTime, toDate) >= 0) ||
                    (SqlMethods.DateDiffDay(fromDate, l.LogoutTime) >= 0 &&
                     SqlMethods.DateDiffDay(l.LogoutTime, toDate) >= 0));
        }

        public IEnumerable<LoginLog> GetLoginLogs(long userId)
        {
            return CompiledLoginLogSerVice.GetLoginLogs(DataContext, userId);
        }
    }

    public static class CompiledLoginLogSerVice
    {
        public static Func<QuizzDataContext, long, LoginLog> GetById =
            CompiledQuery.Compile<QuizzDataContext, long, LoginLog>(
                (ctx, id) => ctx.LoginLogs.FirstOrDefault(l => l.Id == id));

        public static Func<QuizzDataContext, long, LoginLog> GetLastLogin =
            CompiledQuery.Compile<QuizzDataContext, long, LoginLog>(
                (ctx, userId) =>
                ctx.LoginLogs.Where(l => l.UserId == userId).OrderByDescending(l => l.LoginTime).FirstOrDefault());

        public static Func<QuizzDataContext, string, LoginLog> GetBySessionId =
            CompiledQuery.Compile<QuizzDataContext, string, LoginLog>(
                (ctx, session) =>
                ctx.LoginLogs.OrderByDescending(l => l.LoginTime).FirstOrDefault(l => l.SessionId == session));

        public static Func<QuizzDataContext, DateTime, int> GetNumberOfLogin =
            CompiledQuery.Compile<QuizzDataContext, DateTime, int>(
                (ctx, time) => ctx.LoginLogs.Where(l => SqlMethods.DateDiffDay(l.LoginTime, time) == 0).Count());

        public static Func<QuizzDataContext, long, IEnumerable<LoginLog>> GetLoginLogs =
            CompiledQuery.Compile<QuizzDataContext, long, IEnumerable<LoginLog>>(
                (ctx, userId) => ctx.LoginLogs.Where(l => l.UserId == userId).OrderByDescending(l => l.LoginTime));
    }
}
